#pragma once
#include "infer.h"
#include <thread>
#include <functional>
#include <vector>
//#include <nlohmann/json.hpp>
#include <direct.h>
#include <regex>
#include <cmath>

#include "Common/common.h"

template<class T>
class Obj
{
private:
	static bool _instance;
public:

	static std::shared_ptr<T> GetInstance()
	{
		static std::shared_ptr<T> instance(new T);
		return instance;
	}
};

inline std::string GetProgramDir() 
{
	char buf[1024] = "";
	std::string path = std::string();
	_getcwd(buf, sizeof(buf));
	std::regex reg("\\\\");
	path = regex_replace(buf, reg, "/");
	return path;
	
}

class WeldingDetector
{
public:
	WeldingDetector();
	bool Initialize(Params params);
	void SetIuputImages(std::vector<cv::Mat>& image, int id);
	void SetIuputImagessignal(cv::Mat& image, int id);
	void Report(std::function<void(WeldingResult)> callback);
	void ProducerFunc();
	void ConsumerFunc(int id);
	cv::Mat MergeMultiLightImages(const std::vector<cv::Mat>& images, int fusionMethod);
	cv::Mat resize_with_padding(const cv::Mat& input, int target_width, int target_height,
		const cv::Scalar& padding_color);
	cv::Mat resize_with_paddingPlus(const cv::Mat& input, int target_width, int target_height,
		const cv::Scalar& padding_color);
	bool getContourArea(int id, cv::Mat& image, WeldingResult& result);
	
	std::vector<std::thread> m_Consumers;
	std::thread m_Producer;
	InThresholdParam InParam{};

private:
	void Process(int id, const cv::Mat& src, WeldingResult& result);
	void SegandObjDetec(WeldingResult& result);
	std::vector<std::vector<cv::Mat>> loadImageGroups(const std::string& folderPath);

private:
	std::mutex mtx;
	std::condition_variable cvr;
	std::vector<OVYOLOV8> m_Detector;
	std::vector<OVYOLOV8Seg> m_SegDectector;
	std::thread m_ConsumerThread;
	std::thread m_ProductorThread;
	std::queue<std::pair<cv::Mat, int>> m_Images;
	std::queue<std::pair<cv::Mat, int>> m_ImageTeams;
	std::queue<WeldingResult> m_Result;
	float conf_thresh;
	float nms_thresh;
	float Segconf_thresh;
	float Segnms_thresh;
	bool m_initalized;
};

